/**
 * @file Bsp_GpioIIC.c
 * @author 徐松亮 (5387603@qq.com)
 * @version 1.0
 * @date 2023-09-28
 *
 * @copyright Copyright (c) {2030}  沈阳迈思医疗科技有限公司
 *
 * @brief 驱动层-->GPIO模拟IIC通用程序
 */
/* 私有头部文件 (Includes)-----------------------------------------------------*/
#include <stdbool.h>
#include <string.h>
#include "Bsp_GpioIIC.h"
/* 编译警告条件 (Compile warning condition)------------------------------------*/
/* 私有类型定义 (Private typedef)----------------------------------------------*/
/* 私有型宏定义 (Private define)-----------------------------------------------*/
/* 私有常量定义 (Private constants)--------------------------------------------*/
/* 公有常量定义 (Public constants)---------------------------------------------*/
/* 私有变量定义 (Private variables)--------------------------------------------*/
/* 公有变量定义 (Public variables)---------------------------------------------*/
/* 私有函数声明 (Private function prototypes)----------------------------------*/
static void BspGpioIIC_Start(void *_tp_interface);
static void BspGpioIIC_Stop(void *_tp_interface);
static void BspGpioIIC_SendByte(void *_tp_interface, uint8_t _ucByte);
static uint8_t BspGpioIIC_ReadByte(void *_tp_interface);
static uint8_t BspGpioIIC_WaitAck(void *_tp_interface);
static void BspGpioIIC_Ack(void *_tp_interface);
static void BspGpioIIC_NAck(void *_tp_interface);
static uint8_t BspGpioIIC_CheckDevice(void *_tp_interface, uint8_t _Address);
/* 私有函数实体 (Private functions)--------------------------------------------*/
/*
*********************************************************************************************************
*   功能说明: CPU发起I2C总线启动信号
*********************************************************************************************************
*/
static void BspGpioIIC_Start(void *_tp_interface)
{
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, true);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, false);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, false);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
}

/*
*********************************************************************************************************
*   功能说明: CPU发起I2C总线停止信号
*********************************************************************************************************
*/
static void BspGpioIIC_Stop(void *_tp_interface)
{
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, false);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
}

/*
*********************************************************************************************************
*   功能说明: CPU向I2C总线设备发送8bit数据
*********************************************************************************************************
*/
static void BspGpioIIC_SendByte(void *_tp_interface, uint8_t _ucByte)
{
    uint8_t i = 0;
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    // 先发送字节的高位bit7
    for (i = 0; i < 8; i++)
    {
        if (_ucByte & 0x80)
        {
            tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, true);
        }
        else
        {
            tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, false);
        }
        tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
        tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, true);
        tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
        tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, false);
        if (i == 7)
        {
            tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, true);
        }
        _ucByte <<= 1;
        tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    }
}

/*
*********************************************************************************************************
*   功能说明: CPU从I2C总线设备读取8bit数据
*   返 回 值: 读到的数据
*********************************************************************************************************
*/
static uint8_t BspGpioIIC_ReadByte(void *_tp_interface)
{
    uint8_t i = 0;
    uint8_t value = 0;
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    //
    for (i = 0; i < 8; i++)
    {
        value <<= 1;
        tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, true);
        tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
        if (tp_interface->t_Input.fnp_ReadPin(BSP_GPIO_IIC_E_PIN_SDA))
        {
            value++;
        }
        tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, false);
        tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    }
    return value;
}

/*
*********************************************************************************************************
*   功能说明: CPU产生一个时钟，并读取器件的ACK应答信号
*   返 回 值: 返回0表示正确应答，1表示无器件响应
*********************************************************************************************************
*/
static uint8_t BspGpioIIC_WaitAck(void *_tp_interface)
{
    uint8_t re = 0;
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    if (tp_interface->t_Input.fnp_ReadPin(BSP_GPIO_IIC_E_PIN_SDA))
    {
        re = 1;
    }
    else
    {
        re = 0;
    }
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, false);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);

    return re;
}

/*
*********************************************************************************************************
*   功能说明: CPU产生一个ACK信号
*********************************************************************************************************
*/
static void BspGpioIIC_Ack(void *_tp_interface)
{
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, false);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, false);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
}

/*
*********************************************************************************************************
*   功能说明: CPU产生1个NACK信号
*********************************************************************************************************
*/
static void BspGpioIIC_NAck(void *_tp_interface)
{
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SDA, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, true);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
    tp_interface->t_Input.fnp_WritePin(BSP_GPIO_IIC_E_PIN_SCL, false);
    tp_interface->t_Input.fnp_Delay_us(tp_interface->t_Input.Delay_us);
}

/*
*********************************************************************************************************
*   函 数 名: i2c_CheckDevice
*   功能说明: 检测I2C总线设备，CPU向发送设备地址，然后读取设备应答来判断该设备是否存在
*   形    参:  _Address：设备的I2C总线地址
*   返 回 值: 返回值 0 表示正确， 返回1表示未探测到
*********************************************************************************************************
*/
static uint8_t BspGpioIIC_CheckDevice(void *_tp_interface, uint8_t _Address)
{
    uint8_t ucAck = 0;
    BSP_GPIO_IIC_T_INTERFACE *tp_interface = _tp_interface;
    if ((tp_interface->t_Input.fnp_ReadPin(BSP_GPIO_IIC_E_PIN_SDA)) &&
        (tp_interface->t_Input.fnp_ReadPin(BSP_GPIO_IIC_E_PIN_SCL)))
    {
        BspGpioIIC_Start(tp_interface);
        // 发送设备地址+读写控制bit（0 = w， 1 = r) bit7 先传
        BspGpioIIC_SendByte(tp_interface, _Address | BSP_GPIO_IIC_WR);
        ucAck = BspGpioIIC_WaitAck(tp_interface);
        BspGpioIIC_Stop(tp_interface);
        return ucAck;
    }
    return 1;
}
/* 公有函数实体 (Public functions)---------------------------------------------*/
/**
 * @brief
 * @param[in]  _tp_interfaceMy Param doc
 */
void BspGpioIIC_Init(BSP_GPIO_IIC_T_INTERFACE *_tp_interface)
{
    _tp_interface->t_Output.fnp_IIC_Start = BspGpioIIC_Start;
    _tp_interface->t_Output.fnp_IIC_Stop = BspGpioIIC_Stop;
    _tp_interface->t_Output.fnp_IIC_SendByte = BspGpioIIC_SendByte;
    _tp_interface->t_Output.fnp_IIC_ReadByte = BspGpioIIC_ReadByte;
    _tp_interface->t_Output.fnp_IIC_WaitAck = BspGpioIIC_WaitAck;
    _tp_interface->t_Output.fnp_IIC_Ack = BspGpioIIC_Ack;
    _tp_interface->t_Output.fnp_IIC_NAck = BspGpioIIC_NAck;
    _tp_interface->t_Output.fnp_CheckDevice = BspGpioIIC_CheckDevice;
    // 给一个停止信号, 复位I2C总线上的所有设备到待机模式
    _tp_interface->t_Output.fnp_IIC_Stop(_tp_interface);
}
/********************************END OF FILE***********************************/
